#pragma once

#include "Atomic.h"
#include "FreeListPool.h"

namespace WTB{

	class CBitmap{
	public:
		CBitmap();

		~CBitmap();

		/*
		* init the bitmap with _unBitMapSize bit, not in support of multi-thread
		*
		*@parm _unBitMapSize bitmap size(count of bit)
		*
		*@return int: 0(success) -1(failure)
		*
		*/
		int InitBitmap(unsigned int _unBitMapSize);

		/*
		* Un init the bitmap, not in support of multi-thread
		*
		*/
		void UnInitBitmap();

		/*
		* set the _unIndex bit to 1  , in support of multi-thread
		*
		*@parm _unIndex the bit to set
		*
		*@return int: 0,1 the old bit value before set(success) -1(failure)
		*
		*/
		int BitTestAndSet(unsigned int _unIndex);

		/*
		* reset the _unIndex bit to 0, in support of multi-thread
		*
		*@parm _unIndex the bit to reset
		*
		*@return int: 0,1 the old bit value before reset(success) -1(failure)
		*
		*/
		int BitTestAndReset(unsigned int _unIndex);

		/*
		* get the value _unIndex bit, in support of multi-thread
		*
		*@parm _unIndex the bit to set
		*
		*@return int: 0 or 1 (success)  -1(failure)
		*
		*/
		int GetBit(unsigned int _unIndex);


	private:
		unsigned int m_unBitMapSize;
		CAtomic<int> *m_AtomicIntArrayPoint;
		int m_nAtomicIntArraySize;
	private:
		static const int BIT_OF_BYTE = 8;
		static const int BYTE_OF_INT = sizeof(int);
		static const int BIT_OF_INT = BYTE_OF_INT * BIT_OF_BYTE;
		static const unsigned int MAX_BIT_OF_BIT_MAP = 0xffffffff - BIT_OF_INT + 1;
		static const unsigned int MAX_INT_ARRAY_SIZE = MAX_BIT_OF_BIT_MAP / BIT_OF_INT;
	};

	inline CBitmap::CBitmap():
	m_AtomicIntArrayPoint(NULL),
		m_nAtomicIntArraySize(0),
		m_unBitMapSize(0)
	{
	}

	inline CBitmap::~CBitmap()
	{
		UnInitBitmap();
	}

	inline int CBitmap::InitBitmap(unsigned int _unBitMapSize)
	{
		if (_unBitMapSize > MAX_BIT_OF_BIT_MAP || m_nAtomicIntArraySize > 0)
		{
			return -1;
		}

		m_unBitMapSize = _unBitMapSize;

		m_nAtomicIntArraySize = m_unBitMapSize / BIT_OF_INT + 1;

		m_AtomicIntArrayPoint = (CAtomic<int>*) CFreeListPool::Instance()->GetMemory(m_nAtomicIntArraySize * BYTE_OF_INT);

		if (NULL == m_AtomicIntArrayPoint)
		{
			m_unBitMapSize = 0;
			m_nAtomicIntArraySize;
			return -1;
		}

		return 0;
	}

	inline int CBitmap::GetBit(unsigned int _unIndex)
	{
		if (_unIndex >= m_unBitMapSize)
		{
			return -1;
		}
		int nIndex = _unIndex / BIT_OF_INT;
		return m_AtomicIntArrayPoint[nIndex].GetBit(_unIndex % 32);
	}
	inline int CBitmap::BitTestAndReset(unsigned int _unIndex)
	{
		if (_unIndex >= m_unBitMapSize)
		{
			return -1;
		}

		int nIndex = _unIndex / BIT_OF_INT;
		return m_AtomicIntArrayPoint[nIndex].AtomicBitTestAndReset(_unIndex % 32);
	}
	inline int CBitmap::BitTestAndSet(unsigned int _unIndex)
	{
		if (_unIndex >= m_unBitMapSize)
		{
			return -1;
		}

		int nIndex = _unIndex / BIT_OF_INT;
		return m_AtomicIntArrayPoint[nIndex].AtomicBitTestAndSet(_unIndex % 32);
	}
	inline void CBitmap::UnInitBitmap()
	{
		if (NULL != m_AtomicIntArrayPoint)
		{
			CFreeListPool::Instance()->ReleaseMemory((char*)m_AtomicIntArrayPoint,m_nAtomicIntArraySize * BYTE_OF_INT);
			m_AtomicIntArrayPoint = NULL;
		}

		m_nAtomicIntArraySize = 0;
		m_unBitMapSize = 0;
	}

}